package org.swift.mashup.engine.model;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.swift.commons.xml.Match;
import org.swift.commons.xml.Matcher;
import org.swift.mashup.engine.IndexedFile;

public class MatchActivity extends XMLActivity {

	private final String xpathExpression;

	private Activity nextActivity;

	public MatchActivity(String xpathExpression,
			Collection<? extends Parameter> params,
			Map<String, String> namespaces) {
		super(params, namespaces);
		this.xpathExpression = xpathExpression;
	}

	@Override
	public ActivityResultComponent doActivity(ActivityContext context,
			Map<String, ?> parameters) throws ActivityException {

		try {
			if (this.doPersistent(context.getSize())) {
				File workingDir = new File(this.getWorkingDirectory());
				if (!workingDir.exists()) {
					workingDir.mkdirs();
				}
				File file = File.createTempFile("tmp", null, workingDir);
				FileOutputStream xmlSource = new FileOutputStream(file);
				context.writeAll(xmlSource);
				xmlSource.close();
				Iterator<? extends Match> matcher = new Matcher(
					this.xpathExpression, file, this.getNamespaces());
				if (nextActivity == null) {
					return new ActivityResultItem(
						new IndexedFile(file, matcher));
				} else {
					return iterateMatches(matcher, parameters);
				}

			} else {
				Iterator<Match> matcher = new Matcher(this.xpathExpression,
					context.getBytes(), this.getNamespaces());
				if (nextActivity == null) {
					List<String> results = new ArrayList<String>();
					while (matcher.hasNext()) {
						results.add(matcher.next().getValue());
					}
					return new ActivityResultItem(results);
				} else {
					return iterateMatches(matcher, parameters);
				}
			}
		} catch (Exception e) {
			throw new ActivityException(e);
		}
	}

	private ActivityResultComponent iterateMatches(
			Iterator<? extends Match> matcher, Map<String, ?> parameters)
			throws ActivityException {
		List<Object> transformedData = new ArrayList<Object>();
		while (matcher.hasNext()) {
			transformedData.add(nextActivity.doActivity(
				new MatchActivityContext(matcher.next()), parameters).getOutput());
		}
		return new ActivityResultItem(transformedData);
	}

	public void setNextActivity(Activity nextActivity) {
		this.nextActivity = nextActivity;
	}

}
